﻿using Microsoft.Extensions.Logging;
using MQTT.Server.App.Dto;
using MQTT.Server.MqttHandler;
using MQTT.Share.ConfigurationExtension;
using MQTT.Share.MQTT;
using MQTT.Share.MQTT.Message;
using MQTTnet;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace MQTT.Server.App
{
    public class ServerManager : IServerManager
    {
        private IMqttServer MqttServer { get; set; }
        public int SocketPort = 9901;
        private MessageHandler _messageHandler;
        private readonly ILogger<ServerManager> _logger;
        private readonly MqttServerHelper _mqttServerHelper;
        private readonly List<ClientDesc> clients;
        public ServerManager(
            IEnumerable<IMqttServerAdapter> adapters,
            IMqttNetLogger mqttNetlogger,
            IConfigurationManager configurationManager,
            MessageHandler messageHandler,
            MqttServerHelper mqttServerHelper,
            ILogger<ServerManager> logger)
        {
            _logger = logger;
            MqttServer = new MqttFactory().CreateMqttServer(adapters, mqttNetlogger);
            _mqttServerHelper = mqttServerHelper;
            _messageHandler = messageHandler;
            _messageHandler.SetServer(MqttServer);

            clients = _mqttServerHelper.GetClients();

            if (Int32.TryParse(configurationManager.Configuration["MQTT:socket_port"] ?? "9901",
                out var port))
            {
                SocketPort = port;
            }
        }

        public ServerManager Init()
        {

            MqttServer.ClientConnected += (sender, args) =>
            {

                var clientid = args.ClientId;
                //客户端注册
                _logger.LogTrace($"客户端连接【{clientid}】");
                MqttClientContainer.Add(clientid, new ClientDescriptor(clientid));

            };

            MqttServer.ApplicationMessageReceived += (s, e) =>
            {

                //消息处理
                _messageHandler.Handle(new MqttMessage()
                {
                    ClientId = e.ClientId,
                    Body = Encoding.UTF8.GetString(e.ApplicationMessage.Payload),
                    Topic = e.ApplicationMessage.Topic
                });
            };
            return this;
        }

        public async Task StartAsync()
        {

            if (MqttServer == null) return;

            var optionsBuilder = new MqttServerOptionsBuilder()
                .WithConnectionBacklog(100)
                .WithDefaultEndpointPort(SocketPort)

                //客户端订阅消息拦截器
                .WithSubscriptionInterceptor(context =>
                {
                    //客户端避免接收到自己发出的消息
                    context.AcceptSubscription = !context.TopicFilter.Topic.StartsWith(MQTTConsts.MQTT_Topic_Perfix_Client);
                })
                //.WithApplicationMessageInterceptor(context =>
                //{
                //    context.ApplicationMessage.
                //})
                .WithConnectionValidator(context =>
                {
                   
                    var client = clients.Find(m => m.Id == context.Username);
                    if (client == null || client.Password != context.Password)
                    {
                        context.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
                    }
                    else
                    {
                        if (!Guid.TryParse(context.ClientId, out _))
                        {
                            context.ReturnCode = MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
                        }
                        client.ConnectionId = context.ClientId;
                        client.Online = true;
                        context.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
                    }

                    

                })
               ;
            _logger.LogTrace($"MQTT 服务端启动,监听端口【{SocketPort}】");
            await MqttServer.StartAsync(optionsBuilder.Build());
        }

        public async Task StopAsync()
        {
            if (MqttServer == null) return;
            await MqttServer.StopAsync();
        }


        public void SendMsg(string topic, string msg)
        {
            var message = new MqttApplicationMessageBuilder()
                .WithTopic(topic)
                .WithPayload(msg)
                //.WithAtLeastOnceQoS()
                .WithExactlyOnceQoS()
                .WithRetainFlag(false)
                .Build();
            MqttServer.PublishAsync(message);

        }
    }
}
